# 导入所需的库
from Astar import Astar
import json
import time
import readjs as rdj
import numpy as np
import os
import copy
#import route_fy_v2.envs.drawmap as dm
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from itertools import permutations
import JudeI

with open('einsetic\data\cmps.json', 'r', encoding='utf-8') as f:
    cmpsdata = json.load(f)
with open('einsetic\data\Grouptask.json', 'r', encoding='utf-8') as f:
    girddata1 = json.load(f)

def create_cmps_from_json(json_data):
    cmps=JudeI.components(json_data['name'])
    cmps.setdata(json_data)
    return cmps
def create_griddata_from_json(json_data):

    task=JudeI.TaskPipeRouting()
    task.settask(json_data['Grouptask'])
    griddata= JudeI.griddata(
        routing_id=json_data['routing_id'],
        Grouptask=task,
        minpoints=json_data['minpoints'],
        maxpoints=json_data['maxpoints'],
        centerpoint=json_data['centerpoint'],
        resolution_rate=json_data['resolution_rate']
    )
    return griddata

# 创建griddata对象
grid_data_obj = create_griddata_from_json(girddata1)


cmps=create_cmps_from_json(cmpsdata)
girddata=create_griddata_from_json(girddata1)
pipes=None
for i in girddata.Grouptask.group_manage:
    if i.group_id==girddata.routing_id:
        pipes=i
        break


class seqresoult:
    def __init__(self,pipes,info):
        self.pipes=pipes
        self.info=info
        self.paths=[]

class fitnessfromAStar:
    def __init__(self, pipes,grid):
        self.pipes = pipes
        self.grid=grid
        self.seq=pipes.generate_sequence()
        self.outputlist=[]  
        self.output={}
             
     # 获取所有管路对象
    def get_all_pipes(self):
        return self.pipes
    # 插值函数
    def  interpolatepoint(self,M,stpoint,edpoint,step_size):
        n_x=int((np.abs(edpoint[0] - stpoint[0])+1) / step_size)
        n_y=int((np.abs(edpoint[1] - stpoint[1])+1) / step_size)
        n_z=int((np.abs(edpoint[2] - stpoint[2])+1) / step_size)
        n=max(n_x,n_y,n_z)
        x=np.round(np.linspace(stpoint[0], edpoint[0], n), 0).astype(int)
        y=np.round(np.linspace(stpoint[1], edpoint[1], n), 0).astype(int)
        z=np.round(np.linspace(stpoint[2], edpoint[2], n), 0).astype(int)

        interpolated_points= np.array(list(zip(x, y, z)))
        return  interpolated_points 
    
    #端口延伸点
    def pipe_extendpoint(self,point, normal_vector, distance):

        normal_vector = normal_vector / np.linalg.norm(normal_vector)
        extend_point = point + distance * normal_vector

        return extend_point
        
    def calculate_fitness(self, map):
        maplist=[]
        # 遍历排列组合中的每个管路
        total_cost = 0
        
        for i in self.seq:
            # 获取当前管路和下一个管路的起点和终点
           # print(i)
            map1=copy.deepcopy(map)      
            tmppipegroup=[]
            for j in i:
                tmppipeinfodict={}  
                Coordcenterlist=[]
                current_pipe = j
                exp_num=self.grid.pipe_expand(current_pipe.r)
                #print(exp_num)
                #print(current_pipe.name)
                
                extend_distance=20
                #端口面中心点
                s=current_pipe.spoint
                s_e=self.pipe_extendpoint(current_pipe.spoint,current_pipe.svector,extend_distance)#延伸点  
                s=self.grid.convert_to_gobalgrid(s)
                s_e=self.grid.convert_to_gobalgrid(s_e)

                e=current_pipe.epoint
                e_e=self.pipe_extendpoint(current_pipe.epoint,current_pipe.evector,extend_distance)
                e=self.grid.convert_to_gobalgrid(e)
                e_e=self.grid.convert_to_gobalgrid(e_e)
      
                #利用time计时
                start=time.time()

                A=Astar(map1,start=s_e,end=e_e)
                result,info=A.FindPath()
                #print(map1)
                end=time.time()
                print("time:",end-start)
                #print()
                centerlist=[]
                openlist=[]
                closelist=[]
                father=(info.prepoint is None)

                #centerlist.append(e)#加入起始点

                while father==False:
                    centerlist.append(info.position.tolist())
                    info=info.prepoint
                    father=(info.prepoint is None)
                centerlist.append(info.position.tolist())
                for i1 in A.open_set:
                    openlist.append(i1.position.tolist())

                for i1 in A.close_set:
                    closelist.append(i1.position.tolist())
   
                for z in range(len(centerlist) - 1):
                    startpoint = centerlist[z]
                    endpoint = centerlist[z + 1]
                    interpolated_points = self.interpolatepoint(map1,startpoint, endpoint,1)
                    for point in interpolated_points:
                        centerlist.append(point.tolist())
                for i2 in centerlist:
                    map1[i2[0],i2[1],i2[2]]=2
                  
                    for o in exp_num[0]:
                        for p in exp_num[1]:
                            for q in exp_num[2]:
                                if map1[i2[0]+o,i2[1]+p,i2[2]+q]!=2:
                                   map1[i2[0]+o,i2[1]+p,i2[2]+q]=3  
                centerlist.insert(0, e);        
                centerlist.append(s)#加入终止点                     

                current_pipe_fitness= info.cost#当前管路的适应度
                total_cost += current_pipe_fitness#累加到总适应
                
                for k in centerlist:
                    tmppoint=self.grid.convert_grid_to_coord(k)
                    Coordcenterlist.append(tmppoint)

                tmppipeinfodict["管路名称"]=j.pipe_id
                tmppipeinfodict["管路起始端口法向"]=j.svector
                tmppipeinfodict["管路终止端口法向"]=j.evector
                tmppipeinfodict["管路适应度"]=current_pipe_fitness
                tmppipeinfodict["管路中心节点"]=Coordcenterlist

                tmppipegroup.append(tmppipeinfodict)
                tmppipeinfodict={}

            self.output["管路顺序"]=tmppipegroup 
            self.output["当前管路总适应度"]=total_cost

            self.outputlist.append(self.output)
            self.output={}

            maplist.append(map1)            
        return maplist
#生成局部栅格
grid1 = rdj.grid(girddata.resolution_rate,girddata.minpoints,girddata.maxpoints,girddata.centerpoint,cmps)
map=grid1.creat_grid(cmps)  

#计算适应度
fa=fitnessfromAStar(pipes,grid1)
maplist=fa.calculate_fitness(map)

min_fitness=100000
outputresult={}
for i in range(len(fa.outputlist)):
    if(fa.outputlist[i].get("当前管路总适应度")<min_fitness):
        min_fitness=fa.outputlist[i].get("当前管路总适应度")
        outputresult=fa.outputlist[i]

with open('einsetic\data\outputresult.json', 'w', encoding='utf-8') as file:
    json.dump(outputresult, file, ensure_ascii=False, indent=4)

#专门为并行用的栅格
ParaGridinfodict={}
ParallelGridData=rdj.grid(girddata.resolution_rate,girddata.minpoints,girddata.maxpoints,girddata.centerpoint,cmps)
ParallelGridMap=ParallelGridData.creat_grid(cmps)

ParaGridinfodict["resolution_ratio"]=girddata.resolution_rate
ParaGridinfodict["p_min"]=ParallelGridData.p_min
ParaGridinfodict["p_max"]=ParallelGridData.p_max
ParaGridinfodict["theta_min"]=ParallelGridData.theta_min
ParaGridinfodict["theta_max"]=ParallelGridData.theta_max
ParaGridinfodict["z_min"]=ParallelGridData.z_min
ParaGridinfodict["z_max"]=ParallelGridData.z_max
ParaGridinfodict["delta_theta"]=ParallelGridData.delta_theta

ParallelGridMap_list = ParallelGridMap.tolist()#将栅格转为列表，JSON序列化
ParaGridinfodict["ParallelGridMap"]=ParallelGridMap_list

with open('einsetic\data\ParallelGridMap.json', 'w', encoding='utf-8') as file:
    json.dump(ParaGridinfodict, file, indent=4)


#
#
#fig = plt.figure()
#ax = fig.add_subplot(111, projection='3d')
#tensor=maplist[0]
#
#
#s=grid1.convert_to_gobalgrid(ps[0][0].start)
#e=grid1.convert_to_gobalgrid(ps[0][0].end)
#s1=grid1.convert_to_gobalgrid(ps[0][1].start)
#e1=grid1.convert_to_gobalgrid(ps[0][1].end)
#
#
## 获取张量的坐标和值
#x, y, z = np.where(tensor == 2)
#l, m, n = np.where(tensor== 3)
## 在对应的位置上画点
#ax.scatter(x, y, z, c='r', marker='o', alpha=0.5)
#ax.scatter(l, m,n, c='b', marker='o', alpha=0.5)
#ax.scatter(s[0], s[1], s[2] , c='y', marker='o', alpha=1)
#ax.scatter(e[0], e[1], e[2] , c='g', marker='o', alpha=1)
#ax.scatter(s1[0], s1[1], s1[2] , c='y', marker='o', alpha=1)
#ax.scatter(e1[0], e1[1], e1[2] , c='g', marker='o', alpha=1)
##ax.scatter(e_array, f_array, g_array, c='c', marker='o', alpha=0.5)
##ax.scatter(0, 0, 0 , c='y', marker='o', alpha=0.5)
##ax.scatter(tensor.shape[0], tensor.shape[1],  tensor.shape[2] , c='b', marker='o', alpha=0.5)
#ax.set_xlabel('X Label')
#ax.set_ylabel('Y Label')
#ax.set_zlabel('Z Label')
#
#plt.show()













































